import request from '@/api/common'
import {
  onMounted, reactive, ref, toRefs,
  computed, UnwrapRef, watch, createVNode
} from 'vue'
import useBoolean from '@/hooks/useBoolean'
import { Modal } from 'ant-design-vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue'
interface ITabelRespose<T> {
  content: UnwrapRef<T[]>;
  totalElements: number;
}

export enum AopEnum {
  BEFORE_SEARCH = 'beforeSearch',
  AFTER_SEARCH = 'afterSearch',
  FIRST_LOAD = 'firstLoad',
}

declare interface IAopOptions {
  [AopEnum.BEFORE_SEARCH]?: (params?: any) => object;
  [AopEnum.AFTER_SEARCH]?: (params?: any) => object;
  [AopEnum.FIRST_LOAD]: boolean;
}

export default function useTable<T, U = T> (
  baseApi: string,
  aopOptions = ({
    [AopEnum.FIRST_LOAD]: true
  }) as IAopOptions
) {
  const { value: loading, setValue: toggleLoading } = useBoolean(false)
  const searchForm = ref<Partial<U & T>>({} as U & T)
  const initForm = ref({})
  const dataSource = ref<T[]>([])
  const pageConfig = reactive({
    page: 1,
    size: 10,
    total: 0
  })
  const page = computed<number>(() => pageConfig.page - 1)

  watch([page, () => pageConfig.size], handleGetTable)

  async function handleGetTable () {
    toggleLoading(true)
    const beforeParams = aopOptions?.[AopEnum.BEFORE_SEARCH]?.()
    const params = { ...searchForm.value, ...initForm.value, ...beforeParams, ...pageConfig, page: page.value }
    const { totalElements, content } = await request.setPath(baseApi).get<ITabelRespose<T>>(params)
    toggleLoading()
    dataSource.value = content
    pageConfig.total = totalElements
    aopOptions?.[AopEnum.AFTER_SEARCH]?.()
  }

  function handleSearchTable () {
    if (pageConfig.page !== 1) {
      pageConfig.page = 1
      return
    }
    handleGetTable()
  }

  function handleResetTable () {
    searchForm.value = {}
    handleSearchTable()
  }

  onMounted(() => { aopOptions[AopEnum.FIRST_LOAD] && handleGetTable() })

  // curd
  async function handlePutAction (id: number, data: T) {
    await request.setPath(baseApi).put({ id, ...data })
  }

  async function handleDelAction (id: number | number[]) {
    await request.setPath(baseApi).del([id])
  }

  function handleConfirmData (callback: (...args: []) => any, title = '确定操作吗？') {
    Modal.confirm({
      title,
      icon: createVNode(ExclamationCircleOutlined),
      async onOk () {
        await callback()
        // refresh current page table
        handleGetTable()
      }
    })
  }

  function handleEditData (id: number, data: T) {
    handleConfirmData(() => handlePutAction(id, data), '确定修改这条数据吗？')
  }

  function handleDelData (id: number | number[]) {
    handleConfirmData(() => handleDelAction(id), '确定删除这条数据吗？')
  }

  return {
    loading,
    searchForm,
    initForm,
    dataSource,
    ...toRefs(pageConfig),
    handleGetTable,
    handleSearchTable,
    handleResetTable,
    // curd
    handleEditData,
    handleDelData
  }
}
